package p.ithorns.framework.common.utils;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.json.JsonReadFeature;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;

/**
 * JsonUtil
 *
 * @author ithorns
 * @version 1.0
 * @date 2020/5/22 16:40
 */
public class JsonUtil {

    private final static Logger log = LoggerFactory.getLogger(JsonUtil.class);

    private final static ObjectMapper OM;

    static {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss[.SSS]");
        OM = JsonMapper.builder()
                .defaultDateFormat(df)
                .enable(JsonGenerator.Feature.IGNORE_UNKNOWN)
                .enable(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN)
                // 不忽略大小写 针对‘bKey’这样的属性以免会被过滤
                .enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES)
                .enable(JsonReadFeature.ALLOW_MISSING_VALUES)
                .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
                .build()
                .registerModule(new JavaTimeModule());

        //OM.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        //OM.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

        // @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
        //OM.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
    }

    public static ObjectNode createObject(){
        return OM.createObjectNode();
    }

    public static ArrayNode createArray() {
        return OM.createArrayNode();
    }

    public static String toJson(Object object) {
        try {
            return OM.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            log.warn(e.getMessage());
        }

        return null;
    }

    /**
     * Json -> Bean
     *
     * 处理复杂对象必须有空构造函数，否则会有问题
     * 如属性为List的Bean
     *
     * @param json  -
     * @param clazz -
     * @return T
     */
    public static <T> T fromJson(String json, Class<T> clazz) {
        try {
            return OM.readValue(json, clazz);
        } catch (IOException e) {
            log.warn(e.getMessage());
        }

        return null;
    }

    public static <T> T fromJson(String json, TypeReference<T> typeReference) {
        try {
            // new TypeReference<List>
            return OM.readValue(json, typeReference);
        } catch (IOException e) {
            log.warn(e.getMessage());
        }

        return null;
    }

    public static <T> T fromJson(String json, JavaType javaType) {
        try {
             //TypeFactory.defaultInstance().construct...()
            return OM.readValue(json, javaType);
        } catch (IOException e) {
            log.warn(e.getMessage());
        }

        return null;
    }

}